
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/eeprom.h>
#include <string.h>

#include "uart.h"






#if defined (__AVR_ATmega8__)

#include "uart.h"

#define ADC_PORT	PORTC
#define ADC_DDR		DDRC
#define ADC_IN0		0
#define ADC_IN1		1
#define ADC_IN2		2
#define ADC_IN3		3
#define ADC_IN4		4
#define ADC_IN5		5

#define CHANNEL_COUNT 6


#elif defined (__AVR_ATmega16__)

#define ADC_PORT	PORTA
#define ADC_DDR		DDRA
#define ADC_IN0		0
#define ADC_IN1		1
#define ADC_IN2		2
#define ADC_IN3		3
#define ADC_IN4		4

#define CHANNEL_COUNT 5

#endif




volatile static uint16_t current_channel;
volatile uint16_t current_measure[CHANNEL_COUNT];

#if defined (__AVR_ATmega16__)
volatile int32_t integrated_measures[CHANNEL_COUNT];
volatile uint16_t integrated_measures_zero_offset[CHANNEL_COUNT];
#endif

volatile unsigned char NewMeasuresAvaible=0;


unsigned char GetMeasureData(unsigned char *data, unsigned char *data_len)
{
static unsigned char ret=0;

	cli();
		memcpy(data,current_measure,CHANNEL_COUNT*2);
		if(data_len!=NULL) *data_len=CHANNEL_COUNT*2;
		ret=NewMeasuresAvaible;
		NewMeasuresAvaible=0;
	sei();
}


#if defined (__AVR_ATmega16__)


void GetIntegratorValues(unsigned char *data, unsigned char *data_len)
{
	cli();
		memcpy(data,integrated_measures,CHANNEL_COUNT*4);
		*data_len=CHANNEL_COUNT*4;
	sei();
}

void SetIntegratorZeroOffsetValues(unsigned char *data, unsigned char data_len)
{
	if(data_len!=(CHANNEL_COUNT*2)) return;
	
	cli();
		memcpy(integrated_measures_zero_offset,data,CHANNEL_COUNT*2);
	sei();
}

void ResetIntegrators(void)
{
	cli();
		for(unsigned char i=0;i<CHANNEL_COUNT;i++) integrated_measures[i]=0;
	sei();
}

#endif


void AdcSwitchToInternalReference(unsigned char SwitchToInternalReference)
{
cli();
	
	current_channel=0;
	NewMeasuresAvaible=0;
	ADMUX &= 0xE8; // set MUX to 0
	ADCSRA |= (1 << ADSC); // run conversion


   if(SwitchToInternalReference)
   {

	// Set ADC reference to internal (enable capatior)
   	ADMUX |= (1 << REFS0); 
   	ADMUX |= (1 << REFS1); 

   } else
   {
   // Set ADC reference to avcc (enable capatior)
   	ADMUX |= (1 << REFS0); 
   	ADMUX &= ~(1 << REFS1); 
   }

sei();
} 


void prepare_adc_measure()
{

	ADC_DDR  &= ~(1 << ADC_IN0); /* set as input */
	ADC_DDR  &= ~(1 << ADC_IN1); /* set as input */
	ADC_DDR  &= ~(1 << ADC_IN2); /* set as input */
	ADC_DDR  &= ~(1 << ADC_IN3); /* set as input */
	ADC_DDR  &= ~(1 << ADC_IN4); /* set as input */

	ADC_PORT  &= ~(1 << ADC_IN0); /* disable pullups */
	ADC_PORT  &= ~(1 << ADC_IN1); /* disable pullups */
	ADC_PORT  &= ~(1 << ADC_IN2); /* disable pullups */
	ADC_PORT  &= ~(1 << ADC_IN3); /* disable pullups */
	ADC_PORT  &= ~(1 << ADC_IN4); /* disable pullups */

#if defined (__AVR_ATmega8__)

	ADC_DDR  &= ~(1 << ADC_IN5); /* set as input */
	ADC_PORT  &= ~(1 << ADC_IN5); /* disable pullups */

#endif


   ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // Set ADC prescaler to 128 - 125KHz sample rate @ 16MHz

   // Set ADC reference to internal (enable capatior)


   ADMUX |= (1 << REFS0); 
   ADMUX |= (1 << REFS1); 
 
   // No MUX values needed to be changed to use ADC0
   current_channel=0;

 
   ADCSRA |= (1 << ADEN);  // Enable ADC
   ADCSRA |= (1 << ADIE);  // Enable ADC Interrupt
   ADCSRA |= (1 << ADSC);  // Start A2D Conversions 

}




ISR(ADC_vect){ 

current_measure[current_channel]=(uint16_t)ADC;

#if defined (__AVR_ATmega16__)

if((integrated_measures[current_channel]<0xFFFFFFF) && (integrated_measures[current_channel]>(-0xFFFFFFF)))
{
	integrated_measures[current_channel]+=current_measure[current_channel];
	integrated_measures[current_channel]-=integrated_measures_zero_offset[current_channel];
}
 
#endif


if(current_channel<(CHANNEL_COUNT-1)) current_channel++; else 
{
	current_channel=0;
	NewMeasuresAvaible=1;
}

ADMUX &= 0xE8; // set MUX to 0
ADMUX |= (current_channel&7);
ADCSRA |= (1 << ADSC); // run conversion

}
